package com.ruoyi.act.module.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.act.module.domain.ActDeploy;
import com.ruoyi.act.module.service.IDeployService;
import com.ruoyi.common.utils.StringUtils;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.zip.ZipInputStream;

/**
 * 流程管理实现接口
 *
 * @author hcj
 */
@Service
public class DeployServiceImpl implements IDeployService {

    @Autowired
    private RepositoryService repositoryService;

    @Override
    public PageInfo findPage(ActDeploy deploy) {

        DeploymentQuery deploymentQuery = repositoryService.createDeploymentQuery();
        Integer pageNum = deploy.getPageNum() == null ? 0 : deploy.getPageNum() - 1;
        Integer pageSize = deploy.getPageSize() == null ? 10 : deploy.getPageSize();

        if (StringUtils.isNotBlank(deploy.getName())){
            deploymentQuery.deploymentName(deploy.getName());
        }

        if (StringUtils.isNotBlank(deploy.getKey())){
            deploymentQuery.deploymentKey(deploy.getKey());
        }

        if (StringUtils.isNotBlank(deploy.getCategory())){
            deploymentQuery.deploymentCategory(deploy.getCategory());
        }

        if (StringUtils.isNotBlank(deploy.getTenantId())){
            deploymentQuery.deploymentTenantId(deploy.getTenantId());
        }


        List<Deployment> list = deploymentQuery.orderByDeploymenTime().desc().listPage(pageNum * pageSize, pageSize);

        List<Map<String,Object>> mapList = new ArrayList<>();
        list.forEach(info->{
            Map<String,Object> map = new HashMap<>();
            map.put("id",info.getId());
            map.put("category",info.getCategory());
            map.put("name",info.getName());
            map.put("key",info.getKey());
            map.put("tenantId",info.getTenantId());
            map.put("deploymentTime",info.getDeploymentTime());
            map.put("version",info.getVersion());
            mapList.add(map);
        });

        PageInfo pageInfo = PageInfo.of(mapList);
        pageInfo.setTotal(deploymentQuery.count());
        pageInfo.setPageNum(pageNum);
        pageInfo.setPageSize(pageSize);

        return pageInfo;
    }

    @Override
    public Deployment createDeploymentByModel(String modelId) throws IOException {
        Model model = repositoryService.getModel(modelId);
        if (model != null) {
            JsonNode node = new ObjectMapper().readTree(repositoryService.getModelEditorSource(model.getId()));
            byte[] bytes = null;
            BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(node);
            bytes = new BpmnXMLConverter().convertToXML(bpmnModel);

            String processName = model.getName() + ".bpmn20.xml";
            Deployment deployment = repositoryService.createDeployment()
                    .name(model.getName())
                    .key(model.getKey())
                    .category(model.getCategory())
                    .tenantId(model.getTenantId())
                    .addString(processName, new String(bytes, StandardCharsets.UTF_8))
                    .deploy();
            return deployment;
        }

        return null;
    }

    @Override
    public Deployment createDeployment(String filePath, String name) throws FileNotFoundException {

        Deployment deployment = null;

        if (filePath.endsWith(".zip")) {
            deployment = repositoryService.createDeployment()
                    .addZipInputStream(new ZipInputStream(new FileInputStream(filePath)))
                    .name(name)
                    .deploy();
        } else if (filePath.endsWith(".bpmn")) {
            deployment = repositoryService.createDeployment()
                    .addInputStream(filePath, new FileInputStream(filePath))
                    .name(name)
                    .deploy();
        }

        return deployment;
    }

    @Override
    public List<ProcessDefinition> createProcessDefinitionQuery(String processKey) {
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        List<ProcessDefinition> list = processDefinitionQuery.processDefinitionKey(processKey).orderByProcessDefinitionVersion().desc().list();
        return list;
    }

    /**
     * 参数true表示级联删除
     *
     * @param deploy
     */
    @Override
    public void deleteDeployment(ActDeploy deploy) {
        repositoryService.deleteDeployment(deploy.getDeploymentId(), deploy.getCascade());
    }

    @Override
    public void suspendProcessDefinitionById(String processDefinitionId) {
        repositoryService.suspendProcessDefinitionById(processDefinitionId);
    }

    @Override
    public void suspendProcessDefinitionById(String processDefinitionId, Boolean suspendProcessInstances, Date suspensionDate) {
        repositoryService.suspendProcessDefinitionById(processDefinitionId, suspendProcessInstances, suspensionDate);
    }


}
